import { NextFunction, Request, Response } from "express";
import { BoardService, PostService, UserService } from "../services";
import { BoardSchema } from "../schemas";
import { Like } from "typeorm";
import { paginate } from "../utils";
import { RoleUser } from "../entities/user";

export class BoardController {
  public static async create(
    req: Request<unknown, unknown, BoardSchema>,
    res: Response,
    next: NextFunction,
  ) {
    try {
      const user = await UserService.findById(res.locals.user.id);
      if (!user) {
        return res.status(400).json({
          status: "fail",
          message: "Invalid parameters",
        });
      }
      const board = await BoardService.create({ ...req.body, user });
      res.status(201).json(board);
    } catch (err) {
      next(err);
    }
  }

  public static async findOne(req: Request, res: Response, next: NextFunction) {
    try {
      const board = await BoardService.findById(req.params.id);
      if (!board) {
        return res.status(404).json({
          status: "fail",
          message: "Board not found",
        });
      }
      res.json(board);
    } catch (err) {
      next(err);
    }
  }

  public static async findMany(
    req: Request,
    res: Response,
    next: NextFunction,
  ) {
    try {
      const boards = await BoardService.find({
        ...paginate(req),
        where: { title: Like(`%${req.query.q || ""}%`) },
      });
      res.json({
        data: boards[0],
        total: boards[1],
      });
    } catch (err) {
      next(err);
    }
  }

  public static async findPosts(
    req: Request,
    res: Response,
    next: NextFunction,
  ) {
    try {
      const board = await BoardService.findById(req.params.id);
      if (!board) {
        return res.status(404).json({
          status: "fail",
          message: "Board not found",
        });
      }
      const posts = await PostService.find({
        ...paginate(req),
        where: [
          {
            title: Like(`%${req.query.q || ""}%`),
            board: {
              id: board.id,
            },
          },
          {
            content: Like(`%${req.query.q || ""}%`),
            board: {
              id: board.id,
            },
          },
        ],
      });
      res.json({ data: posts[0], total: posts[1] });
    } catch (err) {
      next(err);
    }
  }

  public static async update(req: Request, res: Response, next: NextFunction) {
    try {
      const board = await BoardService.findById(req.params.id);
      if (!board) {
        return res.status(404).json({
          status: "fail",
          message: "Post not found",
        });
      }
      if (
        res.locals.user.id !== board.user.id &&
        res.locals.user.role !== RoleUser.ADMIN
      ) {
        return res.status(403).json({
          status: "fail",
          message: "Not allowed",
        });
      }
      await BoardService.update(board.id, req.body);
      res.sendStatus(200);
    } catch (err) {
      next(err);
    }
  }

  public static async remove(req: Request, res: Response, next: NextFunction) {
    try {
      const board = await BoardService.findById(req.params.id);
      if (!board) {
        return res.status(404).json({
          status: "fail",
          message: "Post not found",
        });
      }
      if (
        res.locals.user.id !== board.user.id &&
        res.locals.user.role !== RoleUser.ADMIN
      ) {
        return res.status(403).json({
          status: "fail",
          message: "Not allowed",
        });
      }
      await BoardService.remove(board);
      res.sendStatus(200);
    } catch (err) {
      next(err);
    }
  }
}
